/*
 * Copyright (c) 2018 Qianxun SI Inc. All rights reserved.
 *
 * File name   : qxwz_rtos_al.h
 *
 * Vesion      :
 *
 * Date        : 2018.11.25
 *
 * Author      :
 *
 * Description :rtos al head file
 *
 * History     : Created in Nov.25 2018
 *
 */

#include "fibo_opencpu.h"
#include "at_engine.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "time.h"
#include "qxwz_rtos_al.h"



#ifdef UART_LOG
#include "ringbuf.h"
#include "console_uart.h"
#endif

double difftime(time_t time1, time_t time2) 
{
 	return time1-time2;
}


qxwz_time_t qxwz_get_boot_ms(void)
{
	return fibo_getSysTick_ext()/1000;
}

/*
 * convert time
 * @param[in]: timestamp:time
               hsm: ptr to msecond
               ysm:ptr to day
 *
 * @return: 0: ok   1:fail
 */
qxwz_tm *qxwz_gmtime(unsigned long long timestamp, double *hsm, int *dmy)
{
    static qxwz_tm current_tm = {0};
    int timeoffset = 32 * CFW_TIME_ZONE_SECOND;
    time_t t = (time_t)(timestamp / 1000 + timeoffset);
    struct tm tm;
    gmtime_r(&t, &tm);
    current_tm.tm_year = (tm.tm_year + 1900);
    current_tm.tm_mon = tm.tm_mon + 1;
    current_tm.tm_mday = tm.tm_mday;
    current_tm.tm_hour = tm.tm_hour;
    current_tm.tm_min = tm.tm_min;
    current_tm.tm_sec = tm.tm_sec;
    current_tm.tm_wday = (current_tm.tm_mday + 1 + 2 * current_tm.tm_mon + 3 * (current_tm.tm_mon + 1) / 5 + current_tm.tm_year + current_tm.tm_year / 4 - current_tm.tm_year / 100 + current_tm.tm_year / 400) % 7;
    
	*dmy = (current_tm.tm_mday)*10000 + current_tm.tm_mon*100 +(current_tm.tm_year -2000);
	*hsm = current_tm.tm_hour*10000 + current_tm.tm_min*100 + current_tm.tm_sec;
	
	return &current_tm;
}

/*
 * @brief: sleep seconds
 * @param[in]  sec: seconds.
 *
 * @return: none
 */
void qxwz_sleep(unsigned int sec)
{
    fibo_taskSleep(sec * 1000);
}

void qxwz_msleep(unsigned int msec)
{
    fibo_taskSleep(msec);
}

void *qxwz_malloc(unsigned int size)
{
    return fibo_malloc(size);
}

void qxwz_free(void *addr)
{
    fibo_free(addr);
}


int qxwz_mutex_create(qxwz_mutex_t *mutex, const char *name)
{
    *mutex = fibo_mutex_create();
    if(*mutex>0)
		return 0;
	else
		return -1;

}

int qxwz_mutex_delete(qxwz_mutex_t *mutex)
{
    fibo_mutex_delete(*mutex);
    return 0;
}

int qxwz_mutex_lock(qxwz_mutex_t *mutex)
{
    fibo_mutex_lock(*mutex);
    return 0;
}

int qxwz_mutex_unlock(qxwz_mutex_t *mutex)
{
	fibo_mutex_unlock(*mutex);
    return 0;
}

int qxwz_sem_create(qxwz_sem_t *sem, const char *name, int value)
{
    *sem = fibo_sem_new(0);
    if(*sem>0)
		return 0;
	else
		return -1;

}

int qxwz_sem_delete(qxwz_sem_t *sem)
{
    fibo_sem_free(*sem);
    return 0;
}

int qxwz_sem_wait(qxwz_sem_t *sem)
{
    fibo_sem_wait(*sem);
    return 0;
}

int qxwz_sem_timedwait(qxwz_sem_t *sem, unsigned int millisec)
{

    bool ret = fibo_sem_try_wait(*sem, millisec);
    if(ret == true)
		return 0;
	else
		return -1;
}

int qxwz_sem_post(qxwz_sem_t *sem)
{
   fibo_sem_signal(*sem);
   return 0;
}


int qxwz_thread_create(qxwz_thread_t *th, const qxwz_thread_attr_t *attr, void *(*start_routine)(void *), void *arg)
{
    //int ret = fibo_thread_create(start_routine, attr->name, attr->stacksize, NULL, attr->priority + OSI_PRIORITY_NORMAL);
    int ret = fibo_thread_create_ex(start_routine, attr->name, attr->stacksize, NULL, OSI_PRIORITY_NORMAL, th );
    return ret == 0 ? 0 : -1;
}

int qxwz_thread_start(qxwz_thread_t id)
{
	//return fibo_thread_start(id);
	fibo_thread_resume( id );
    return 0;
}

int qxwz_thread_join(qxwz_thread_t thread, void **retval)
{
	//return fibo_thread_join(thread);
    return 0;
}

int qxwz_thread_cancel(qxwz_thread_t thread)
{
	//return fibo_thread_suspend(thread);
	fibo_thread_suspend( thread );
	return 0;
}

char * task_test_name="test";
char * task_name_fail="qx_name_fail";

#define task_name_max_len 20
char *qxwz_get_thread_name(void)
{
	UINT32 id;
/*	
	static unsigned char name[task_name_max_len-1]={0};
	unsigned char *p;
	int test_len;
	p = fibo_thread_getName();
	test_len = strlen(p)>task_name_max_len? task_name_max_len:strlen(p);
	fibo_textTrace("task name len=%d",test_len);
	memcpy(name,p,test_len);
	return name;
*/
	static unsigned char name[task_name_max_len-1]={0};

	id = fibo_thread_id();
	if(id>0){
		//fibo_textTrace("qxwz_get_thread_name %x",id);
		memcpy(name, "qx_",3);
		char str[25]={0};
		itoa(id, str, 16);
		memcpy(name+3, str,strlen(str));
		return name;
		//return task_test_name;
	} else {
		return task_name_fail;
	}

	
	//return task_test_name;
}





#ifdef UART_LOG
static struct ringbuf g_log_rb;
char log_buf_init_flag = 0;
unsigned char xlog_ringbuf[1024 * 128];


void log_buffer_write(unsigned char *data, int len)
{ 
	if(log_buf_init_flag==1){
       //fibo_textTrace("logTask write enter");
        ringbuf_write(&g_log_rb, data, (size_t)len);
	}

}


void logTask(void *nul) 
{
    static unsigned char buffer[4096*2];
	int len;
	ringbuf_init(&g_log_rb, xlog_ringbuf, sizeof(xlog_ringbuf));
	log_buf_init_flag = 1;
	fibo_textTrace("logTask enter");	
    for (;;) {
			while (ringbuf_length(&g_log_rb) > 0)
			{
				//fibo_textTrace("logTask have data");
				len = ringbuf_read(&g_log_rb, buffer, sizeof(buffer));
				if (len > 0)
				{
					fibo_hal_uart_put(CONSOLE_UART, buffer, len);
				}
				//qxwz_msleep(100);
			}
			qxwz_msleep(100);
		//fibo_textTrace("logTask loop");		
    }
}

#endif
int qxwz_trace(unsigned char *data, int len)
{
#ifdef UART_LOG
	log_buffer_write(data,len);
#else
	fibo_textTrace("%s",data);
#endif
    return 0;
}


